package com.baymax.test.scene.demo

import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.ViewFlipper
import androidx.core.view.setPadding
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.baymax.test.scene.BaseScene
import com.baymax.test.scene.addButton
import com.baymax.test.scene.addDFView
import com.baymax.test.scene.internal.Downloader
import com.baymax.test.scene.internal.ViewIndicator
import com.baymax.test.scene.newSceneFlexContainer
import com.bytedance.scene.Scene
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.yield
import okhttp3.internal.io.FileSystem
import okio.BufferedSink
import okio.BufferedSource
import okio.HashingSink
import okio.Okio
import okio.Sink
import okio.Source
import okio.blackholeSink
import okio.buffer
import java.io.Closeable
import java.io.File
import kotlin.random.Random

class CircleScene : BaseScene() {

    override fun onCreateView(p0: LayoutInflater, p1: ViewGroup, p2: Bundle?): View {
        val context = p1.context
        return p1.newSceneFlexContainer {
            val circle = CircleProgressView(context)
            circle.setBackgroundColor(Color.argb(153, 0, 0, 0))
            addDFView(300, 500, circle) {

            }

            addButton("restart") {
                circle.setValue(100)
            }

            addButton("checkMd5") {
                launch(Dispatchers.IO) {
                    val copyTo = File(context.externalCacheDir, "apk/a.apk")
                    val localFileMd5 = HashingSink.md5(blackholeSink()).use { hs ->
                        FileSystem.SYSTEM.source(copyTo).buffer().readAll(hs)
                        hs.hash.hex()
                    }
                    println("md5 $localFileMd5")
                }
            }

            addButton("download") {
                launch(Dispatchers.IO) {
                    Downloader().apply {
                        download(
                            context,
                            "test",
                            "http://192.168.31.110:5500/a.apk",
                            "ADE9EA6E79800239E103F1284415AF9E"
                        ) { p, d ->
                            circle.setValue(p)
                            println("progress -> $p")
                        }
                    }
                }
            }

            val singleCase = SingleScheduleCase(lifecycleScope)
            launch {
                lifecycle.repeatOnLifecycle(Lifecycle.State.DESTROYED) {
                    singleCase.close()
                }
            }

            addButton("busy work") {
                singleCase.busyWork()
            }
            addButton("cust work") {
                singleCase.custWork()
            }

            val indicator = IndicatorCase(this@CircleScene)
            addDFView(-2, 60, indicator.case) {
                this.totalSize = 0
                this.setBackgroundColor(Color.argb(153, 0, 0, 0))
            }

            addButton("next") {
                indicator.next()
            }

            val flipper = ViewFlipperCase(this@CircleScene)

            addDFView(300, 300, flipper.flipper) {
                val vf = this
                launch {
                    while (true) {
                        delay(3000)
                        vf.showNext()
                    }
                }
            }

        }
    }


    class ViewFlipperCase(private val scene: com.bytedance.scene.Scene) {
        val flipper = ViewFlipper(scene.requireSceneContext())

        val images = listOf(
            "http://images.center.bcs.ottcn.com:8080/images/ysten/picture/ncos/cmjs/2021/12/29/4cdd4cf1222a4ed1b52409675e9049fc.jpg",
            "http://images.center.bcs.ottcn.com:8080/images/ysten/picture/ndms/cmjs/2023/09/22/9d92dec63b3344bfab99817334907f4e.png",
            "http://images.center.bcs.ottcn.com:8080/images/ysten/images/lanmudianbo/tvsouauto/tvsoudianyin/27936192d47b45b48fdb35ddffc9286f.jpg",
            "http://images.center.bcs.ottcn.com/images/ysten/ccscenter/cos/hengban/3529285.jpg",
            "http://images.center.bcs.ottcn.com:8080/poster/2019-10-24/3fbdf4d0cd1a426f8cf4cb604dc0cf49.jpg",
        )

        init {
            setData(images)
        }


        fun setData(imgs: List<String>) {
            val r = Random(System.currentTimeMillis())
            flipper.removeAllViews()
            imgs.forEach {
                val img = View(scene.requireSceneContext())
                img.setBackgroundColor(Color.rgb(r.nextInt(256), r.nextInt(256), r.nextInt(256)))
                flipper.addView(img)
            }
        }
    }

    class SingleScheduleCase(private val scope: CoroutineScope) : Closeable {
        private val channel = Channel<TASK>(1)
        private val limit = Dispatchers.IO.limitedParallelism(4)
        private val singleContext = Dispatchers.IO.limitedParallelism(1)

        init {
//            scope.launch(singleContext) {
//                println("task start ")
//                channel.receiveAsFlow()
//                    .map { download2(it) }
//                    .collect {
//                        println("task complete $it")
//                    }
//            }
        }

        override fun close() {
            singleContext.cancel()
        }

        fun busyWork() {
            scope.launch {
                repeat(10) {
                    println("download1 work --->")
                    val file = download2(task = TASK(it))
                    println("download2 work --->")
                }
            }


        }

        fun custWork() {
            scope.launch(singleContext) {
                println("cust work --->")
                Thread.sleep(100)
                println("cust work ---> out")
                val file = download2(task = TASK(-1))
                println("cust work ---> $file")
            }
        }

        private suspend fun download2(task: TASK): TASK {
            return coroutineScope {
                val d = download(task).await()
                println("task complete1 $d")
                d
            }
        }

        suspend fun download(task: TASK): Deferred<TASK> {
            return coroutineScope {
                async(limit) {
                    repeat(3) {
                        println("T $task => $it")
                        Thread.sleep(500)
                        yield()
                    }
                    task
                }

            }
        }

        data class TASK(val id: Int)

    }

    class IndicatorCase(val scene: Scene) {
        fun next() {
            case.next()
        }

        val case = ViewIndicator(scene.requireSceneContext()).apply {
            setPadding(16)
        }


    }

//    private fun Source.buffer(): BufferedSource = this.buffer()
//    private fun Sink.buffer(): BufferedSink = this.buffer()
}